手写属性访问函数
js
/**
* 安全访问嵌套对象属性,支持数组索引
* @param {Object} obj - 目标对象
* @param {string} path - 属性路径,例如 'a.b[0].c'
* @param {any} [defaultValue=undefined] - 默认值
* @returns {any} 属性值或默认值
*/
function getProperty(obj, path, defaultValue) {
// 1. 路径解析:拆分成属性名和数组索引
const segments = [];
const regex = /([^\.\[\]]+)|\[(\d+)\]/g;
let match;
while ((match = regex.exec(path)) !== null) {
if (match[1]) { // 捕获属性名
segments.push(match[1]);
} else if (match[2]) { // 捕获数组索引
segments.push(parseInt(match[2], 10));
}
}
// 2. 逐级访问属性
let current = obj;
for (const segment of segments) {
if (current === null || current === undefined) break;
current = current[segment];
}
// 3. 返回最终值或默认值
return current !== undefined ? current : defaultValue;
}
// 示例测试
const obj = {
user: {
name: 'John',
hobbies: [
{ title: 'Coding', tags: ['js', 'node'] },
{ title: 'Gaming' }
],
'special.property': 'Secret' // 包含特殊字符的属性
}
};
// 测试用例
console.log(getProperty(obj, 'user.name')); // 'John'
console.log(getProperty(obj, 'user.hobbies[0].tags[1]')); // 'node'
console.log(getProperty(obj, 'user.hobbies[1].title')); // 'Gaming'
console.log(getProperty(obj, 'user.hobbies[3]', 'Not Found')); // 'Not Found'
console.log(getProperty(obj, 'user["special.property"]')); // undefined(需特殊处理)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50